package se.webbzon.oschi01.j3d;

import java.awt.GraphicsConfiguration;

import javax.media.j3d.Appearance;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GraphicsContext3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TriangleArray;
import javax.vecmath.Vector3d;

/**
 * This class is an extension of the Java3D class javax.media.j3d.Canvas3D.
 * The extension fixes some of the bugs related to the standard Canvas3D.
 * Just like the standard Canvas3D this class does not support serialization.
 * 
 * @version	1.0.0.0 Mar 11, 2013
 * @author	Oscar Hinrichsen (oschi01)
 * @see 	Canvas3D
 */
public class ExtendedCanvas3D extends Canvas3D {
	
	// Auto generated serial version UID
	private static final long serialVersionUID = 3194287591332067989L;
	
	// The workaround components
	private final GraphicsContext3D graphicsContext3D;
	private final TriangleArray forcedLastGeometry;
	private final Transform3D geometryTransform;
	
	/*============================================================
	Constructors
	============================================================*/

	/**
	 * Constructs and initializes a new Canvas3D object that Java 3D can render into. The following Canvas3D attributes are initialized to default values as shown:
	 * 		left manual eye in image plate : (0.142, 0.135, 0.4572)
	 *		right manual eye in image plate : (0.208, 0.135, 0.4572)
	 *		stereo enable : true
	 *		double buffer enable : true
	 *		monoscopic view policy : View.CYCLOPEAN_EYE_VIEW
	 *		off-screen mode : false
	 *		off-screen buffer : null
	 *		off-screen location : (0,0)
	 * @param graphicsConfiguration		a valid GraphicsConfiguration object that 
	 * 									will be used to create the canvas. This object 
	 * 									should not be null and should be created using a 
	 * 									GraphicsConfigTemplate3D or the getPreferredConfiguration() 
	 * 									method of the SimpleUniverse utility. For backward compatibility
	 * 									with earlier versions of Java 3D, a null or default 
	 * 									GraphicsConfiguration will still work when used to create 
	 * 									a Canvas3D on the default screen, but an error message will be 
	 * 									printed. A NullPointerException or IllegalArgumentException 
	 * 									will be thrown in a subsequent release.
	 * 
	 * @since 1.0.0.0
	 * 
	 * @throws IllegalArgumentException	if the specified GraphicsConfiguration does not 
	 * 									support 3D rendering
	 */
	public ExtendedCanvas3D(GraphicsConfiguration graphicsConfiguration) {
		this(graphicsConfiguration,false);
	}
	
	/**
	 * 
	 * @param graphicsConfiguration		a valid GraphicsConfiguration object that will be used
	 * 									to create the canvas. This must be created either with 
	 * 									a GraphicsConfigTemplate3D or by using the 
	 * 									getPreferredConfiguration() method of the SimpleUniverse utility.
	 * @param offScreen					a flag that indicates whether this canvas is an off-screen 
	 * 									3D rendering canvas. Note that if offScreen is set to true, 
	 * 									this Canvas3D object cannot be used for normal rendering; 
	 * 									it should not be added to any Container object.
	 * 
	 * @since 1.0.0.0 (Java3D 1.2)
	 * 
	 * @throws IllegalArgumentException	if the specified GraphicsConfiguration does not 
	 * 									support 3D rendering
	 * @throws NullPointerException		if the GraphicsConfiguration is null.
	 */
	public ExtendedCanvas3D(GraphicsConfiguration graphicsConfiguration, boolean offScreen) {
		super(graphicsConfiguration,offScreen);
		
		// Apply workaround
		graphicsContext3D = getGraphicsContext3D();
		graphicsContext3D.setAppearance(new Appearance());
		forcedLastGeometry = new TriangleArray(3, TriangleArray.COORDINATES);
		float[] floatVerts = {0, 0, 0, 0, 1, 0, 0, 0, 1};
		forcedLastGeometry.setCoordinate(0, floatVerts);
		Vector3d geometryPosition = new Vector3d(Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE);
		geometryTransform = new Transform3D();
		geometryPosition.set(geometryPosition);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public void postRender() {
		graphicsContext3D.setModelTransform(geometryTransform);
		graphicsContext3D.draw(forcedLastGeometry);
	}

}
